﻿/*************************************************************************************
 * 工    具：  HK_AutoSwitchToUTF8
 * 
 * 描    述：  本工具是一个 Unity 编辑器扩展工具，
 *            旨在解决在 Unity 中导入或新建脚本时，因编码问题导致的中文字符乱码现象。
 *            当在 Unity 中新建或导入脚本（例如 .cs 或 .csv 文件）时，
 *            若脚本的编码不是 UTF-8，可能会在 Inspector 面板预览或编辑脚本时出现中文乱码。
 *            为了自动解决这个问题，本工具会在资产导入过程中自动检测并转换脚本文件的编码。
 * 
 * 版    本：  V1.1
 * 作    者：  京产肠饭、Kane、谭潇杰
 * 
 * 创    建：  2022/01/15  V1.0
 * 
 * 更    新：  2024/09/30  V1.1
 *            1.修复Bug，同时导入多个脚本时，可能会遗漏脚本检测
 *            2.添加脚本重新编码时的异常捕获，确保在发生错误时程序不会崩溃
 * 
 * 链    接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using UnityEditor;
using System.IO;
using System.Text;
using UnityEngine;

namespace HKTools
{
    [InitializeOnLoad]
    public class HK_AutoSwitchToUTF8 : AssetPostprocessor
    {
        public static void ChangeState(bool isActive)
        {
            isEnabled = isActive;
        }

        static bool isEnabled = true;

        // 将新建脚本转换为UTF-8
        static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
        {
            if (!isEnabled)
                return;

            // 如果没有导入新资源的话，直接return
            if (importedAssets.Length == 0)
                return;

            string dicPath = Directory.GetCurrentDirectory();

            foreach (string importedAsset in importedAssets)
            {
                // 如果不是Assets中的脚本资源，则忽略
                if (!importedAsset.Contains("Assets/"))
                    continue;

                string filePath = Path.Combine(dicPath, importedAsset);

                // 根据名字+创建时间 来判断是否处理过这个文件
                string existKey = importedAsset + new FileInfo(filePath).CreationTime; 

                if (EditorPrefs.GetString(existKey) == "IsProcessed")
                    continue;

                string extension = Path.GetExtension(filePath);

                if (extension == ".cs" || extension == ".CS" || extension == ".CSV" || extension == ".csv")
                {
                    Encoding encoding = GetFileEncodeType(filePath);

                    string key = importedAsset + new FileInfo(filePath).CreationTime;

                    if (encoding == Encoding.UTF8)
                    {
                        Debug.Log(importedAsset + " 已经是UTF-8编码，无需处理");
                        EditorPrefs.SetString(key, "IsProcessed");
                        continue;
                    }

                    try
                    {
                        var fileAllTxt = File.ReadAllText(filePath, encoding);
                        File.WriteAllText(filePath, fileAllTxt, Encoding.UTF8);
                        Debug.Log($"将 {importedAsset} 转为UTF-8编码格式");
                        EditorPrefs.SetString(key, "IsProcessed");
                    }
                    catch (System.Exception ex)
                    {

                        Debug.LogError($"转换文件编码时出错：{importedAsset} 异常信息：{ex.Message}");
                    }
                }
            }
        }

        public static Encoding GetFileEncodeType(string filename)
        {
            using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                if (fs.Length < 2)
                {
                    // 文件小于2字节，无法判断编码，返回默认编码
                    return Encoding.Default;
                }

                BinaryReader br = new BinaryReader(fs);
                byte[] buffer = br.ReadBytes(2);

                if (buffer[0] >= 0xEF)
                {
                    if (buffer[0] == 0xEF && buffer[1] == 0xBB)
                    {
                        return Encoding.UTF8;
                    }
                    else if (buffer[0] == 0xFE && buffer[1] == 0xFF)
                    {
                        return Encoding.BigEndianUnicode;
                    }
                    else if (buffer[0] == 0xFF && buffer[1] == 0xFE)
                    {
                        return Encoding.Unicode;
                    }
                    else
                    {
                        return Encoding.Default;
                    }
                }
                else
                {
                    return Encoding.Default;
                }
            }
        }
    }
}